package com.uduemc.biso.node.module.common.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.uduemc.biso.node.core.common.entities.FormContainer;
import com.uduemc.biso.node.core.common.entities.SiteContainer;
import com.uduemc.biso.node.core.common.entities.publishdata.databody.ComponentData;
import com.uduemc.biso.node.core.common.entities.publishdata.databody.ContainerData;
import com.uduemc.biso.node.core.common.entities.publishdata.databody.componentdata.ComponentDataItemDelete;
import com.uduemc.biso.node.core.common.entities.publishdata.databody.componentdata.ComponentDataItemUpdate;
import com.uduemc.biso.node.core.common.entities.publishdata.databody.containerdata.ContainerDataItemDelete;
import com.uduemc.biso.node.core.common.entities.publishdata.databody.containerdata.ContainerDataItemInsert;
import com.uduemc.biso.node.core.common.entities.publishdata.databody.containerdata.ContainerDataItemUpdate;
import com.uduemc.biso.node.core.common.entities.publishdata.databody.containerdata.RepertoryId;
import com.uduemc.biso.node.core.entities.SComponent;
import com.uduemc.biso.node.core.entities.SContainer;
import com.uduemc.biso.node.core.entities.SContainerForm;
import com.uduemc.biso.node.core.entities.SContainerQuoteForm;
import com.uduemc.biso.node.core.entities.SRepertoryQuote;
import com.uduemc.biso.node.core.entities.custom.RepertoryQuote;
import com.uduemc.biso.node.module.common.mapper.CContainerMapper;
import com.uduemc.biso.node.module.common.mapper.CRepertoryMapper;
import com.uduemc.biso.node.module.common.service.CContainerService;
import com.uduemc.biso.node.module.service.SComponentService;
import com.uduemc.biso.node.module.service.SContainerFormService;
import com.uduemc.biso.node.module.service.SContainerQuoteFormService;
import com.uduemc.biso.node.module.service.SContainerService;
import com.uduemc.biso.node.module.service.SRepertoryQuoteService;

import cn.hutool.core.collection.CollectionUtil;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class CContainerServiceImpl implements CContainerService {

	@Autowired
	private SContainerService sContainerServiceImpl;

	@Autowired
	private SContainerFormService sContainerFormServiceImpl;

	@Autowired
	public SComponentService sComponentServiceImpl;

	@Autowired
	private CRepertoryMapper cRepertoryMapper;

	@Autowired
	private SRepertoryQuoteService sRepertoryQuoteServiceImpl;

	@Autowired
	private CContainerMapper cContainerMapper;

	@Autowired
	private SContainerQuoteFormService sContainerQuoteFormServiceImpl;

	@Transactional
	@Override
	public void publish(long hostId, long siteId, long pageId, ContainerData containerData, ComponentData componentData,
			ThreadLocal<Map<String, Long>> containerTmpIdHolder) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {

		List<ContainerDataItemInsert> insertList = containerData.getInsert();

		List<ContainerDataItemUpdate> updateList = containerData.getUpdate();

		List<ContainerDataItemDelete> deleteList = containerData.getDelete();

		log.info(insertList.toString());

		Map<String, Long> containerTmpId = containerTmpIdHolder.get();

		insertList(hostId, siteId, insertList, containerTmpId);

		updateList(hostId, siteId, updateList, containerTmpId);

		deleteList(hostId, siteId, deleteList, componentData);

	}

	@Transactional
	@Override
	public void insertList(long hostId, long siteId, List<ContainerDataItemInsert> containerDataItemInsertList, Map<String, Long> containerTmpId) {
		if (CollectionUtils.isEmpty(containerDataItemInsertList)) {
			return;
		}
		Iterator<ContainerDataItemInsert> iterator = containerDataItemInsertList.iterator();
		while (iterator.hasNext()) {
			ContainerDataItemInsert containerDataItemInsert = iterator.next();
			SContainer sContainer = containerDataItemInsert.getSContainer(hostId, siteId, containerTmpId);
			if (sContainer == null) {
				throw new RuntimeException("通过 containerDataItemInsert 获取 sContainer 数据失败 containerDataItemInsert： " + containerDataItemInsert.toString());
			}

			SContainer insert = sContainerServiceImpl.insert(sContainer);
			if (insert == null) {
				throw new RuntimeException("写入数据失败，sContainer ： " + sContainer.toString());
			}

			containerTmpId.put(containerDataItemInsert.getTmpId(), insert.getId());

			// 验证是否存有资源数据
			List<RepertoryId> repertoryIds = containerDataItemInsert.getRepertory();
			if (!CollectionUtils.isEmpty(repertoryIds)) {
				Iterator<RepertoryId> iteratorRepertory = repertoryIds.iterator();
				int orderNum = 1;
				while (iteratorRepertory.hasNext()) {
					// 肯定是新增数据
					RepertoryId repertoryId = iteratorRepertory.next();
					SRepertoryQuote sRepertoryQuote = new SRepertoryQuote();
					sRepertoryQuote.setId(null);
					sRepertoryQuote.setHostId(hostId);
					sRepertoryQuote.setSiteId(siteId);
					sRepertoryQuote.setParentId(0L).setRepertoryId(repertoryId.getRepertoryId()).setType((short) 10);
					sRepertoryQuote.setAimId(insert.getId());
					sRepertoryQuote.setOrderNum(repertoryId.getOrdern() == null ? orderNum++ : repertoryId.getOrdern().intValue()).setConfig("");
					SRepertoryQuote insertSRepertoryQuote = sRepertoryQuoteServiceImpl.insert(sRepertoryQuote);
					if (insertSRepertoryQuote == null || insertSRepertoryQuote.getId() == null || insertSRepertoryQuote.getId().longValue() < 1) {
						throw new RuntimeException("写入数据失败，insertSRepertoryQuote ： " + insertSRepertoryQuote.toString());
					}
				}
			}

			List<ContainerDataItemInsert> children = containerDataItemInsert.getChildren();
			if (!CollectionUtils.isEmpty(children)) {
				insertList(hostId, siteId, children, containerTmpId);
			}
		}
	}

	@Transactional
	@Override
	public void updateList(long hostId, long siteId, List<ContainerDataItemUpdate> containerDataItemUpdateList, Map<String, Long> containerTmpId) {
		if (CollectionUtils.isEmpty(containerDataItemUpdateList)) {
			return;
		}
		// 更新
		Iterator<ContainerDataItemUpdate> iteratorUpdate = containerDataItemUpdateList.iterator();
		while (iteratorUpdate.hasNext()) {
			ContainerDataItemUpdate containerDataItemUpdate = iteratorUpdate.next();

			SContainer sContainer = containerDataItemUpdate.getSContainer(hostId, siteId, containerTmpId);

			if (sContainer == null) {
				throw new RuntimeException("通过 containerDataItemUpdate 获取 sContainer 数据为空 containerDataItemUpdate： " + containerDataItemUpdate.toString());
			}

			// 验证id
			if (!sContainerServiceImpl.isExist(sContainer.getId(), sContainer.getHostId(), sContainer.getSiteId(), sContainer.getPageId())) {
				throw new RuntimeException("通过 containerDataItemUpdate 获取 sContainer 验证id数据不存在 sContainer： " + sContainer.toString());
			}

			if (sContainer.getParentId() == null) {
				throw new RuntimeException("通过 containerDataItemUpdate 获取 sContainer 验证parentId数据为空 sContainer： " + sContainer.toString());
			}

			// 验证parentId
			if (sContainer.getParentId().longValue() > 0) {
				if (!sContainerServiceImpl.isExist(sContainer.getParentId(), sContainer.getHostId(), sContainer.getSiteId(), sContainer.getPageId())) {
					throw new RuntimeException("通过 containerDataItemUpdate 获取 sContainer 验证parentId数据不存在 sContainer： " + sContainer.toString());
				}
			}

			if (sContainer.getBoxId() == null) {
				throw new RuntimeException("通过 containerDataItemUpdate 获取 sContainer 验证boxId数据为空 sContainer： " + sContainer.toString());
			}

			// 验证parentId
			if (sContainer.getBoxId().longValue() > 0) {
				if (!sContainerServiceImpl.isExist(sContainer.getBoxId(), sContainer.getHostId(), sContainer.getSiteId(), sContainer.getPageId())) {
					throw new RuntimeException("通过 containerDataItemUpdate 获取 sContainer 验证boxId数据不存在 sContainer： " + sContainer.toString());
				}
			}

			SContainer update = sContainerServiceImpl.updateById(sContainer);

			if (update == null || update.getId().longValue() != sContainer.getId().longValue()) {
				throw new RuntimeException("对 sContainer 数据进行更新失败： " + sContainer.toString());
			}

			List<RepertoryId> repertoryIds = containerDataItemUpdate.getRepertory();
			List<RepertoryQuote> listRepertoryQuote = sRepertoryQuoteServiceImpl.findRepertoryQuoteByHostSiteTypeAimId(hostId, siteId, (short) 10,
					update.getId(), "`s_repertory_quote`.`order_num` ASC");
			if (CollectionUtils.isEmpty(repertoryIds)) {
				listRepertoryQuote.forEach(item -> {
					sRepertoryQuoteServiceImpl.deleteById(item.getSRepertoryQuote().getId());
				});
			} else {
				if (CollectionUtils.isEmpty(listRepertoryQuote)) {
					int orderNum = 1;
					for (RepertoryId repertoryId : repertoryIds) {
						// 肯定是新增数据
						SRepertoryQuote sRepertoryQuote = new SRepertoryQuote();
						sRepertoryQuote.setId(null);
						sRepertoryQuote.setHostId(hostId);
						sRepertoryQuote.setSiteId(siteId);
						sRepertoryQuote.setParentId(0L).setRepertoryId(repertoryId.getRepertoryId()).setType((short) 10);
						sRepertoryQuote.setAimId(update.getId());
						sRepertoryQuote.setOrderNum(repertoryId.getOrdern() == null ? orderNum++ : repertoryId.getOrdern().intValue()).setConfig("");
						SRepertoryQuote insertSRepertoryQuote = sRepertoryQuoteServiceImpl.insert(sRepertoryQuote);
						if (insertSRepertoryQuote == null || insertSRepertoryQuote.getId() == null || insertSRepertoryQuote.getId().longValue() < 1) {
							throw new RuntimeException("写入数据失败，insertSRepertoryQuote ： " + insertSRepertoryQuote.toString());
						}
					}
				} else {
					for (int i = 0; i < listRepertoryQuote.size(); i++) {
						RepertoryQuote repertoryQuote = listRepertoryQuote.get(i);
						RepertoryId repertoryId = null;
						if (i <= repertoryIds.size() - 1) {
							repertoryId = repertoryIds.get(i);
						}

						if (repertoryId == null) {
							sRepertoryQuoteServiceImpl.deleteById(repertoryQuote.getSRepertoryQuote().getId());
						} else {
							SRepertoryQuote sRepertoryQuote = repertoryQuote.getSRepertoryQuote();
							sRepertoryQuote.setRepertoryId(repertoryId.getRepertoryId());
							if (repertoryId.getOrdern() != null) {
								sRepertoryQuote.setOrderNum(repertoryId.getOrdern());
							}
							sRepertoryQuoteServiceImpl.updateByIdSelective(sRepertoryQuote);
						}
					}
					if (repertoryIds.size() > listRepertoryQuote.size()) {
						for (int i = listRepertoryQuote.size(); i < repertoryIds.size(); i++) {
							RepertoryId repertoryId = repertoryIds.get(i);
							// 肯定是新增数据
							SRepertoryQuote sRepertoryQuote = new SRepertoryQuote();
							sRepertoryQuote.setId(null);
							sRepertoryQuote.setHostId(hostId);
							sRepertoryQuote.setSiteId(siteId);
							sRepertoryQuote.setParentId(0L).setRepertoryId(repertoryId.getRepertoryId()).setType((short) 10);
							sRepertoryQuote.setAimId(update.getId());
							sRepertoryQuote.setOrderNum(repertoryId.getOrdern() == null ? i + 1 : repertoryId.getOrdern().intValue()).setConfig("");
							SRepertoryQuote insertSRepertoryQuote = sRepertoryQuoteServiceImpl.insert(sRepertoryQuote);
							if (insertSRepertoryQuote == null || insertSRepertoryQuote.getId() == null || insertSRepertoryQuote.getId().longValue() < 1) {
								throw new RuntimeException("写入数据失败，insertSRepertoryQuote ： " + insertSRepertoryQuote.toString());
							}
						}
					}
				}
			}
		}

	}

	@Transactional
	@Override
	public void deleteList(long hostId, long siteId, List<ContainerDataItemDelete> containerDataItemDeleteList, ComponentData componentData) {
		if (CollectionUtils.isEmpty(containerDataItemDeleteList)) {
			return;
		}
		// TODO Auto-generated method stub
		Iterator<ContainerDataItemDelete> iteratorDelete = containerDataItemDeleteList.iterator();
		while (iteratorDelete.hasNext()) {
			ContainerDataItemDelete containerDataItemDelete = iteratorDelete.next();
			SContainer findOne = sContainerServiceImpl.findOne(containerDataItemDelete.getId());
			// 验证 id
			if (findOne == null || findOne.getId() == null || findOne.getHostId() == null || findOne.getSiteId() == null
					|| findOne.getHostId().longValue() != hostId || findOne.getSiteId().longValue() != siteId) {
				throw new RuntimeException("通过 containerDataItemDelete的id 获取 sContainer 失败 containerDataItemDelete： " + containerDataItemDelete.toString());
			}

			if (findOne.getTypeId() != null || findOne.getTypeId().longValue() == 3L) {
				// 删除的如果是一个容器组件，则该容器组件中不能存在展示组件，或者展示组件也在此次删除当中
				SComponent sComponent = sComponentServiceImpl.findOneByContainerIdStatus(hostId, siteId, findOne.getId(), (short) 0);
				if (sComponent != null) {
					List<ComponentDataItemDelete> componentDataItemDeleteList = componentData.getDelete();
					boolean isExistInDelList = false;
					if (!CollectionUtils.isEmpty(componentDataItemDeleteList)) {
						for (ComponentDataItemDelete componentDataItemDelete : componentDataItemDeleteList) {
							if (componentDataItemDelete != null && componentDataItemDelete.getId() == sComponent.getId().longValue()) {
								isExistInDelList = true;
								break;
							}
						}
					}

					List<ComponentDataItemUpdate> componentDataItemUpdateList = componentData.getUpdate();
					// 是否在更新的列表中
					boolean isExistInUpdList = false;
					if (!CollectionUtils.isEmpty(componentDataItemUpdateList)) {
						for (ComponentDataItemUpdate componentDataItemUpdate : componentDataItemUpdateList) {
							if (componentDataItemUpdate != null && componentDataItemUpdate.getId() == sComponent.getId().longValue()) {
								isExistInUpdList = true;
								break;
							}
						}
					}

					if (!isExistInDelList && !isExistInUpdList) {
						throw new RuntimeException("数据库 s_component 表中存在此次需要删除的容器组件ID， 同时展示组件不在本次删除数据当中， 也不在本次更新的数据当中！");
					}
				}
			}

			// 是否存在已改容器组件作为父级的数据存在，并且该数据还不在本次删除的数据当中
			List<SContainer> parentSContainer = sContainerServiceImpl.findByParentIdAndStatus(hostId, siteId, findOne.getId(), (short) 0);
			if (CollectionUtil.isNotEmpty(parentSContainer)) {
				// 验证是否存在此次删除的数据当中
				for (SContainer parent : parentSContainer) {
					boolean isExistInDel = false;
					for (ContainerDataItemDelete containerDataItemDel : containerDataItemDeleteList) {
						if (containerDataItemDel.getId() == parent.getId().longValue()) {
							isExistInDel = true;
							break;
						}
					}
					if (!isExistInDel) {
						throw new RuntimeException("数据库 s_container 表中存在此次需要删除的子容器组件ID， 同时子容器组件不在本次删除数据当中！");
					}
				}

			}

			// 修改状态为删除
			findOne.setStatus((short) 4);
			SContainer updateAllById = sContainerServiceImpl.updateById(findOne);
			if (updateAllById == null || updateAllById.getId() == null || updateAllById.getId().longValue() != containerDataItemDelete.getId()) {
				throw new RuntimeException("通过 查询出来的 findOne 更新 statue 为4进行删除失败，findOne： " + findOne.toString());
			}

			// 过滤 containerBox 类型的情况！
			if (findOne.getTypeId().longValue() == 3) {
				// 这里删除掉 s_container_quote_form 表对应的数据
				sContainerQuoteFormServiceImpl.deleteByHostSiteContainerId(hostId, siteId, findOne.getId());
			}
		}
	}

	@Override
	public List<SiteContainer> findByHostSitePageId(long hostId, long siteId, long pageId) {
		List<SContainer> listSContainer = sContainerServiceImpl.findByHostSitePageId(hostId, siteId, pageId, (short) 0);
		List<SiteContainer> listSiteContainer = new ArrayList<SiteContainer>();

		Iterator<SContainer> iterator = listSContainer.iterator();
		List<RepertoryQuote> repertoryQuote = null;
		while (iterator.hasNext()) {
			SContainer sContainer = iterator.next();
			repertoryQuote = null;

			// 只有主容器才需要查询资源引用数据表
			if (sContainer.getTypeId() != null && sContainer.getTypeId().longValue() == 1L) {
				repertoryQuote = cRepertoryMapper.findReqpertoryQuoteAllByHostSiteAimIdAndType(hostId, siteId, sContainer.getId(), 10L,
						"`s_repertory_quote`.`order_num` ASC, `s_repertory_quote`.`id` ASC");
			}

			SiteContainer siteContainer = new SiteContainer();
			siteContainer.setSContainer(sContainer).setRepertoryQuote(repertoryQuote);
			listSiteContainer.add(siteContainer);
		}

		return listSiteContainer;
	}

	@Override
	public List<SiteContainer> findInfosByHostSitePageParentIdAndAreaStatus(long hostId, long siteId, long pageId, long parentId, short area, short status) {
		List<SContainer> listSContainer = sContainerServiceImpl.findInfosByHostSitePageParentIdAndAreaStatus(hostId, siteId, pageId, parentId, area, status);
		List<SiteContainer> listSiteContainer = new ArrayList<SiteContainer>();
		Iterator<SContainer> iterator = listSContainer.iterator();
		List<RepertoryQuote> repertoryQuote = null;
		while (iterator.hasNext()) {
			SContainer sContainer = iterator.next();
			repertoryQuote = null;

			// 只有主容器才需要查询资源引用数据表
			if (isRepertoryQuote(sContainer.getTypeId())) {
				repertoryQuote = cRepertoryMapper.findReqpertoryQuoteAllByHostSiteAimIdAndType(hostId, siteId, sContainer.getId(), 10L,
						"`s_repertory_quote`.`order_num` ASC, `s_repertory_quote`.`id` ASC");
			}

			SiteContainer siteContainer = new SiteContainer();
			siteContainer.setSContainer(sContainer).setRepertoryQuote(repertoryQuote);
			listSiteContainer.add(siteContainer);
		}

		return listSiteContainer;
	}

	/**
	 * 通过 typeId 判断是否需要进行资源索引查询
	 * 
	 * @return
	 */
	protected static boolean isRepertoryQuote(Long typeId) {
		if (typeId == null) {
			return false;
		}
		if (typeId.longValue() == 1L || typeId.longValue() == 4L) {
			return true;
		}
		return false;
	}

	@Override
	public List<FormContainer> findFormInfosByHostSiteIdStatusOrder(long hostId, long siteId, short status, String orderBy) {
		List<SContainerForm> listSContainerForm = sContainerFormServiceImpl.findInfosByHostSiteIdStatus(hostId, siteId, status, orderBy);
		if (CollectionUtils.isEmpty(listSContainerForm)) {
			return null;
		}
		return makeFormContainer(listSContainerForm);
	}

	@Override
	public List<SContainerQuoteForm> findQuoteFormInfosByHostSiteIdStatus(long hostId, long siteId, short status) {
		List<SContainerQuoteForm> listSContainerQuoteForm = cContainerMapper.getSContainerQuoteFormByHostSiteIdAndStatus(hostId, siteId, status);
		return listSContainerQuoteForm;
	}

	@Override
	public List<FormContainer> findFormInfosByHostSiteFormIdStatusOrder(long hostId, long siteId, long formId, short status, String orderBy) {
		List<SContainerForm> listSContainerForm = sContainerFormServiceImpl.findInfosByHostSiteFormIdStatus(hostId, siteId, formId, status, orderBy);
		if (CollectionUtils.isEmpty(listSContainerForm)) {
			return null;
		}
		return makeFormContainer(listSContainerForm);
	}

	/**
	 * 通过参数 List<SContainerForm> 制作生成 List<FormContainer>
	 * 
	 * @param listSContainerForm
	 * @return
	 */
	protected List<FormContainer> makeFormContainer(List<SContainerForm> listSContainerForm) {
		List<FormContainer> result = new ArrayList<>();
		Iterator<SContainerForm> iterator = listSContainerForm.iterator();
		while (iterator.hasNext()) {
			SContainerForm sContainerForm = iterator.next();

			FormContainer formContainer = new FormContainer();
			formContainer.setContainerForm(sContainerForm);

			result.add(formContainer);
		}

		return result;
	}

	@Override
	public SContainerQuoteForm findQuoteFormByContainerId(long containerId, short status) {
		List<SContainerQuoteForm> listSContainerQuoteForm = cContainerMapper.findQuoteFormByContainerId(containerId, status);
		if (CollectionUtils.isEmpty(listSContainerQuoteForm)) {
			return null;
		} else if (listSContainerQuoteForm.size() > 1) {
			for (int i = 1; i < listSContainerQuoteForm.size(); i++) {
				SContainerQuoteForm item = listSContainerQuoteForm.get(i);
				sContainerQuoteFormServiceImpl.deleteById(item.getId());
			}
		}
		return listSContainerQuoteForm.get(0);
	}

	@Transactional
	@Override
	public void delete(long hostId, long siteId, long pageId) {
		// 先删除 s_container_quote_form
		sContainerQuoteFormServiceImpl.deleteByHostSitePageId(hostId, siteId, pageId);

		// 删除资源引用部分
		sRepertoryQuoteServiceImpl.deleteSContainerRepertoryByHostSitePageId(hostId, siteId, pageId);

		// 删除
		sContainerServiceImpl.deleteByHostSitePageId(hostId, siteId, pageId);

	}

}
